package com.feeyo.prophet.actions.flight;

import com.alibaba.fastjson.JSON;
import com.feeyo.llm.agent.engine.*;
import com.feeyo.llm.util.JsonUtil;
import com.feeyo.prophet.plugins.FlightScheduleActionUtils;
import com.feeyo.prophet.pojo.action.fleet.FleetAttributesEventVo;
import com.feeyo.prophet.pojo.action.fleet.FleetAttributesResp;
import com.feeyo.prophet.pojo.action.flight.FleetAttribute;
import com.feeyo.prophet.pojo.action.functioncall.flight.FleetAttributesProperties;
import com.feeyo.prophet.pojo.action.functioncall.FunctionCall;
import com.feeyo.prophet.pojo.action.functioncall.ItemsBean;
import com.feeyo.prophet.pojo.action.functioncall.flight.common.BasicTypeDefaultList;
import com.feeyo.prophet.config.ParametersSingletonManager;
import com.feeyo.prophet.plugins.AnswerUtils;
import com.feeyo.prophet.plugins.DbSearchActionUtils;
import com.feeyo.prophet.plugins.FleetAttributesActionUtils;
import com.google.common.collect.Lists;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.http.HttpStatus;

import java.util.*;

/**
 * 机队信息Action
 * 当下南航机队在役和封存的飞机数量是多少?详情怎么样?
 * <p>
 * 当下南航机队有几种机型?
 * 找出南航机队 PW1000G机型, GE90机型明细
 * 当下南航机队中每一种机型对应的飞机数量和对应的飞机编号明细?
 * <p>
 * 当下工银金租的机队数量在役和封存和订单中的飞机数量是多少? 详情怎么样?
 * <p>
 * 请从机龄、出租人维度分析南航机队的飞机分布，并生成对应的分布图
 * 从机龄维度分析南航机队的飞机分布图
 * 从出租人维度分析南航机队的飞机分布图
 *
 * 请从机型、承租人、机龄维度分析工银金租的飞机
 * 请从机型维度分析工银金租的飞机
 * 请从承租人维度分析工银金租的飞机
 * <p>
 * 商飞目前运营的ARJ飞机数量和C919数量
 * 商飞目前运营的ARJ飞机数量和C919数量
 * 商飞目前运营的ARJ飞机数量和C919数量及明细
 * <p>
 * B6606的所有历史事件
 * 获取6606飞机的所有历史事件
 *
 * @author li
 */
@Slf4j
public class FleetAttributesAction implements Action {

    private final String host;
    private final Integer port;

    public FleetAttributesAction(String host, Integer port) {
        this.host = host;
        this.port = port;
    }

    @Override
    public String human() {
        return "机队信息查询";
    }

    @Override
    public String name() {
        return "FleetAttributesAction";
    }

    @Override
    public String eg() {
        return """
                Question: 当下南航机队在役和封存的飞机数量是多少?
                Thought: 我应该使用FleetAttributesAction搜索工具来查找机队相关信息
                Action: FleetAttributesAction
                Action Input: {"operatorIata":"CZ", "aircraftStatus":["Storage","In Service"]}
                """;
    }

    @Override
    public String description() {
        return """
                机队信息查询。包括运营者机队查询，租赁商机队查询，运营商机队分析，租赁商机队分析，制造商机队分析，和获取某架飞机的所有历史事件
                """;
    }

    @Override
    public String parameters() {
        String parameters = ParametersSingletonManager.getParameters("FleetAttributesAction", () -> {
            FunctionCall functionCall = new FunctionCall();
            functionCall.setType("object");
            functionCall.setRequired(Lists.newArrayList("fields"));
            FleetAttributesProperties properties = new FleetAttributesProperties();
            properties.setOperatorIata(new BasicTypeDefaultList("string", "运营者航空公司IATA代码，例如: 'CZ'"));
            properties.setAircraftStatus(new BasicTypeDefaultList("array", "飞机状态集合，例如: ['In Service', 'Order']", new ItemsBean("string", Lists.newArrayList("In Service", "LoI", "On Option", "Option LoI", "Order", "Storage", "Termination of Histories"))));
            properties.setManager(new BasicTypeDefaultList("string", "飞机租赁公司/租赁商（即管理者）缩写，例如: 'ICBC Leasing'"));
            properties.setAircraftManufacturer(new BasicTypeDefaultList("string", "制造商缩写，例如: 'COMAC'"));
            properties.setAircraftTypeList(new BasicTypeDefaultList("array", "制造商产品集合，例如: ['ARJ']", new ItemsBean("string")));
            properties.setAircraftId(new BasicTypeDefaultList("number", "飞机ID，仅数字，例如: 6606"));
            List<ResultScheme.ResultAttach> resultAttachList = result().getResultAttachList();
            List<String> fieldsList = resultAttachList.stream().map(ResultScheme.ResultAttach::getName).toList();
            // 修改 fields 部分，确保生成正确的字段列表
            properties.setFields(new BasicTypeDefaultList("array", "返回结果字段集合(根据需要多选), 各个字段含义解释如下: " + JsonUtil.marshalToString(resultAttachList)
                    + "。可选填字段如下: " + String.join(", ", fieldsList) + ",你需要尽量全面的选出适用字段。可以选多，不要选少。", new ItemsBean("string"), 1));
            functionCall.setProperties(properties);
            return functionCall.toString();
        });
        return parameters;
    }

    @Override
    public ParameterScheme defaultParameters() {
        Map<String, ParameterScheme.Property> properties = new HashMap<>();
        ParameterScheme.Property operatorIataProperty = new ParameterScheme.Property();
        operatorIataProperty.setType("string");
        operatorIataProperty.setDescription("运营者航空公司IATA代码，例如: 'CZ'");
        properties.put("operatorIata", operatorIataProperty);
        ParameterScheme.Property aircraftStatusProperty = new ParameterScheme.Property();
        aircraftStatusProperty.setType("array");
        aircraftStatusProperty.setDescription("飞机状态集合，例如: ['In Service', 'Order']");
        ParameterScheme.Property.Items aircraftStatusItems = new ParameterScheme.Property.Items();
        aircraftStatusItems.setType("string");
        aircraftStatusItems.setEnums(List.of("In Service", "LoI", "On Option", "Option LoI", "Order", "Storage", "Termination of Histories"));
        aircraftStatusProperty.setItems(aircraftStatusItems);
        properties.put("aircraftStatus", aircraftStatusProperty);
        ParameterScheme.Property managerProperty = new ParameterScheme.Property();
        managerProperty.setType("string");
        managerProperty.setDescription("飞机租赁公司/租赁商（即管理者）缩写，例如: 'ICBC Leasing'");
        properties.put("manager", managerProperty);
        ParameterScheme.Property aircraftManufacturerProperty = new ParameterScheme.Property();
        aircraftManufacturerProperty.setType("string");
        aircraftManufacturerProperty.setDescription("制造商缩写，例如: 'COMAC'");
        properties.put("aircraftManufacturer", aircraftManufacturerProperty);
        ParameterScheme.Property aircraftTypeListProperty = new ParameterScheme.Property();
        aircraftTypeListProperty.setType("array");
        aircraftTypeListProperty.setDescription("制造商产品集合，例如: ['ARJ']");
        ParameterScheme.Property.Items aircraftTypeListItems = new ParameterScheme.Property.Items();
        aircraftTypeListItems.setType("string");
        aircraftTypeListProperty.setItems(aircraftTypeListItems);
        properties.put("aircraftTypeList", aircraftTypeListProperty);
        ParameterScheme.Property aircraftIdProperty = new ParameterScheme.Property();
        aircraftIdProperty.setType("string");
        aircraftIdProperty.setDescription("飞机ID，仅数字，例如: '6606'");
        properties.put("aircraftId", aircraftIdProperty);
        List<ResultScheme.ResultAttach> resultAttachList = result().getResultAttachList();
        List<String> fieldsList = resultAttachList.stream().map(ResultScheme.ResultAttach::getName).toList();
        ParameterScheme.Property fieldsProperty = new ParameterScheme.Property();
        fieldsProperty.setType("array");
        fieldsProperty.setDescription("返回结果字段集合(根据需要多选), 字段含义: " + JsonUtil.marshalToString(resultAttachList)
                + "，可选字段: " + String.join(", ", fieldsList));
        ParameterScheme.Property.Items fieldsItems = new ParameterScheme.Property.Items();
        fieldsItems.setType("string");
        fieldsProperty.setItems(fieldsItems);
        fieldsProperty.setMinItems(1);
        properties.put("fields", fieldsProperty);
        ParameterScheme parameterScheme = new ParameterScheme("object", List.of("fields"), properties);
        return parameterScheme;
    }

    @Override
    public ResultScheme result() {
        ResultScheme resultScheme = new ResultScheme();
        List<ResultScheme.ResultAttach> resultAttachList = Lists.newArrayList();
        resultAttachList.add(new ResultScheme.ResultAttach("aircraftId", "integer", "飞机编号"));
        resultAttachList.add(new ResultScheme.ResultAttach("serialNumber", "string", "MSN"));
        resultAttachList.add(new ResultScheme.ResultAttach("aircraftType", "string", "飞机制造商的标识"));
        resultAttachList.add(new ResultScheme.ResultAttach("hexcode", "string", "hexcode"));
        resultAttachList.add(new ResultScheme.ResultAttach("aircraftMasterSeries", "string", "机型"));
        resultAttachList.add(new ResultScheme.ResultAttach("manager", "string", "承租人/租赁者"));
        resultAttachList.add(new ResultScheme.ResultAttach("aircraftStatus", "string", "飞机状态"));
        resultAttachList.add(new ResultScheme.ResultAttach("buildYear", "integer", "飞机建造年份"));
        resultAttachList.add(new ResultScheme.ResultAttach("engineTypeName", "string", "飞机发动机型号"));
        resultAttachList.add(new ResultScheme.ResultAttach("operator", "string", "飞机运营商"));
        resultScheme.setResultAttachList(resultAttachList);
        return resultScheme;
    }

    @Override
    public ActionResult run(String question, String input, ExecuteOptions options) throws Exception {
        try {
            FleetAttribute req = JSON.parseObject(input, FleetAttribute.class);
            // 第一个 运营者  + 状态
            String operatorIata = req.getOperatorIata();
            List<String> aircraftStatus = req.getAircraftStatus();
            // 第二个 租赁者 + 状态
            String manager = req.getManager();
            // 第三个 制造商+ 产品
            String aircraftManufacturer = req.getAircraftManufacturer();
            List<String> aircraftTypeList = req.getAircraftTypeList();
            // 第四个 飞机ID
            String aircraftId = req.getAircraftId();
            // 查询机队信息
            if (CollectionUtils.isNotEmpty(aircraftTypeList)) {
                aircraftManufacturer = operatorIata;
            }
            StringBuilder qSb = new StringBuilder("缺少参数如下:");
            if (StringUtils.isEmpty(operatorIata) && StringUtils.isEmpty(manager) && StringUtils.isEmpty(aircraftId) && StringUtils.isEmpty(aircraftManufacturer)) {
                qSb.append("所查询的航司或者管理公司必填,请使用 conversation action 让用户补充这些参数");
                return new ActionResult(HttpStatus.BAD_REQUEST.value(), qSb.toString());
            }
            List<String> aircraftStatusList = FleetAttributesActionUtils.getAircraftList(aircraftStatus);
            ResultScheme resultScheme = FlightScheduleActionUtils.resultScheme(req.getFields(), result());
            // 查询运营商机队信息 & 每一种机型及机号
            if (StringUtils.isNotEmpty(operatorIata) && CollectionUtils.isEmpty(aircraftTypeList)) {
                return getOperatorAircraft(operatorIata, aircraftStatusList, input,resultScheme);
            }
            // 查询租赁商管理机队信息
            if (StringUtils.isNotEmpty(manager)) {
                return getOperatorManager(manager, aircraftStatusList, input, resultScheme);
            }
            // 制造商机队信息
            if (StringUtils.isNotEmpty(aircraftManufacturer) && CollectionUtils.isNotEmpty(aircraftTypeList)) {
                return getAircraftManufacturerAnalysis(aircraftManufacturer, aircraftTypeList, input, resultScheme);
            }
            // 获取架飞机的所有历史事件
            if (StringUtils.isNotEmpty(aircraftId)) {
                return getAircraftEvent(aircraftId, input, resultScheme);
            }
            return new ActionResult( HttpStatus.BAD_REQUEST.value(), "暂不支持该条件查询");
        } catch (Throwable e) {
            log.error("error", e);
            return new ActionResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), "解析发生错误，请思考后再调用？");
        }
    }

    /**
     * 获取某架飞机的所有历史事件
     *
     * @param aircraftId 飞机标识Id
     * @param input      输入
     */
    private ActionResult getAircraftEvent(String aircraftId, String input, ResultScheme resultScheme) {
        String respTxt = null;
        try {
            respTxt = DbSearchActionUtils.queryOperatorEventAircraft(host, port, aircraftId);
        } catch (Exception e) {
            log.error("getAircraftEvent error", e);
        }
        if (StringUtils.isEmpty(respTxt)) {
            return new ActionResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), "飞机历史事件信息查询发生错误，请稍后再试");
        }
        // 数据解析成List
        List<FleetAttributesEventVo> operatorList = FleetAttributesActionUtils.getOperatorEventDetail(respTxt);
        operatorList.sort(Comparator.comparing(FleetAttributesEventVo::getStartEvent));
        if (operatorList.isEmpty()) {
            return new ActionResult(HttpStatus.BAD_REQUEST.value(), "飞机历史事件信息数据不存在");
        }
        return AnswerUtils.answer(name(), input, operatorList, resultScheme);
    }

    /**
     * 制造商机队信息
     *
     * @param aircraftManufacturer 制造商
     * @param input                输入
     */
    private ActionResult getAircraftManufacturerAnalysis(String aircraftManufacturer, List<String> aircraftTypeList, String input, ResultScheme resultScheme) {
        String respTxt = null;
        try {
            respTxt = DbSearchActionUtils.queryOperatorAircraft(host, port, null, null, aircraftManufacturer, null, aircraftTypeList);
        } catch (Exception e) {
            log.error("getAircraftManufacturerAnalysis error", e);
        }
        if (StringUtils.isEmpty(respTxt)) {
            return new ActionResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), "制造商机队信息查询发生错误，请稍后再试");
        }
        List<FleetAttributesResp> operatorList = FleetAttributesActionUtils.getOperatorDetail(respTxt);
        operatorList.sort(Comparator.comparing(FleetAttributesResp::getAircraftType));
        if (operatorList.isEmpty()) {
            return new ActionResult(HttpStatus.BAD_REQUEST.value(), "制造商机队信息不存在，请稍后再用");
        }
        return AnswerUtils.answer(name(), input, operatorList, resultScheme);
    }

    /**
     * 航司机队分析
     *
     * @param manager 租赁商
     * @param input   输入
     */
    private ActionResult getOperatorManager(String manager, List<String> aircraftStatusList, String input, ResultScheme resultScheme) {
        String respTxt = null;
        try {
            respTxt = DbSearchActionUtils.queryOperatorAircraft(host, port, null, manager, null, aircraftStatusList, null);
        } catch (Exception e) {
            log.error("airportResult error", e);
        }
        if (StringUtils.isEmpty(respTxt)) {
            return new ActionResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), "机场查询发生错误，请稍后再试");
        }
        List<FleetAttributesResp> operatorList = FleetAttributesActionUtils.getOperatorDetail(respTxt);
        operatorList.sort(Comparator.comparing(FleetAttributesResp::getAircraftMasterSeries));
        if (operatorList.isEmpty()) {
            return new ActionResult(HttpStatus.BAD_REQUEST.value(), "机场数据不存在，请稍后再用");
        }
        return AnswerUtils.answer(name(), input, operatorList,resultScheme);
    }

    /**
     * 机队信息
     *
     * @param operatorIata       运营者航空公司IATA代码
     * @param aircraftStatusList 状态:在役,订单中, 退役
     * @param input              输入
     */
    private ActionResult getOperatorAircraft(String operatorIata, List<String> aircraftStatusList, String input, ResultScheme resultScheme) {
        String respTxt = null;
        try {
            respTxt = DbSearchActionUtils.queryOperatorAircraft(host, port, operatorIata, null, null, aircraftStatusList, null);
        } catch (Exception e) {
            log.error("airportResult error", e);
        }
        if (StringUtils.isEmpty(respTxt)) {
            return new ActionResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), "机场查询发生错误，请稍后再试");
        }
        List<FleetAttributesResp> operatorList = FleetAttributesActionUtils.getOperatorDetail(respTxt);
        operatorList.sort(Comparator.comparing(FleetAttributesResp::getAircraftStatus));
        if (operatorList.isEmpty()) {
            return new ActionResult(HttpStatus.BAD_REQUEST.value(), "机场数据不存在，请稍后再用");
        }
        return AnswerUtils.answer(name(), input, operatorList,resultScheme);
    }
}